package com.incar.chuxing.ble.manager;

import java.util.concurrent.LinkedBlockingDeque;

import com.incar.chuxing.ble.bean.ControlResult;
import com.incar.chuxing.ble.bean.OrderCmd;
import com.incar.chuxing.ble.utils.AtomicIntegerUtil;
import com.incar.chuxing.ble.utils.ConvertUtil;
import com.incar.chuxing.ble.utils.HexUtil;
import com.incar.chuxing.ble.utils.Logger;
import com.incar.chuxing.ble.utils.PhoneUtils;

/**
 * Created by xiongjida on 2017/6/19.
 */

/**
 * 管理BLE所有指令的获取
 */
public class DeviceControlManager
{

    /**
     * 消息头
     */
    private static final byte[] header = new byte[] { 0x7E, 0x10 };

    private volatile static DeviceControlManager instance;

    private DeviceControlManager()
    {
    }

    public static DeviceControlManager getInstance()
    {
        if (instance == null)
        {
            synchronized (DeviceControlManager.class)
            {
                if (instance == null)
                {
                    instance = new DeviceControlManager();
                }
            }
        }
        return instance;
    }

    /**
     * 获取控制指令
     * 
     * @param cmd 控制指令
     * @param controllCiphertext 加密密文
     */
    public OrderCmd getDeviceControlCmd(String cmd, String controllCiphertext,
            LinkedBlockingDeque<ControlResult> mControlCmds)
    {
        Logger.e("cmd:" + cmd);
        // 报文序列号,占用2字节
        byte[] serialNum = getSerialNum();
        // 命令标识,占用2个字节
        byte[] cmdIdentifier = new byte[] { 0x0A, 0x01 };
        // 控制密文,16字节
        byte[] controllCipherByte = HexUtil.hexStringToByteArray(controllCiphertext);
        // 控制指令
        byte[] controlCmd = ConvertUtil.stringToBytes(cmd);
        // 控制密文长度
        byte[] controlCmdLength = new byte[] { (byte) controlCmd.length };
        // 时间戳
        byte[] time = ConvertUtil.intToBytes(PhoneUtils.getCurrentTimeSecond(), true);
        // 内容
        byte[] content = ConvertUtil.byteMerger(serialNum, cmdIdentifier, controllCipherByte,
                controlCmdLength, controlCmd, time);
        // 指定指令
        byte[] controlBytes = ConvertUtil.crcEncrypt(content, header);
        mControlCmds.clear();
        // ControlResult controlResult = new
        // ControlResult(String.valueOf(System.currentTimeMillis()),
        // HexUtil.encodeHexStr(controlBytes));
        ControlResult controlResult = new ControlResult(String.valueOf(System.currentTimeMillis()),
                cmd);
        mControlCmds.offer(controlResult);
        return new OrderCmd(controlBytes, controlResult);

    }

    /**
     * 获取状态指令
     * 
     * @return
     */
    public OrderCmd getDeviceStateCmd()
    {
        // 报文序列号,占用2字节
        byte[] serialNum = getSerialNum();
        // 命令标识,占用2个字节
        byte[] cmdIdentifier = new byte[] { 0x0A, 0x06 };
        // 时间戳
        byte[] time = ConvertUtil.intToBytes(PhoneUtils.getCurrentTimeSecond(), true);
        // 内容
        byte[] content = ConvertUtil.byteMerger(serialNum, cmdIdentifier, time);
        // 获取指令
        return new OrderCmd(ConvertUtil.crcEncrypt(content, header));
    }

    /**
     * 获取电量,里程等相关信息
     * 
     * @return
     */
    public OrderCmd getDeviceCarInfo()
    {
        // 报文序列号,占用2字节
        byte[] serialNum = getSerialNum();
        // 命令标识,占用2个字节
        byte[] cmdIdentifier = new byte[] { 0x02, (byte) 0x98 };
        // 时间戳
        byte[] time = ConvertUtil.intToBytes(PhoneUtils.getCurrentTimeSecond(), true);
        // 内容
        byte[] content = ConvertUtil.byteMerger(serialNum, cmdIdentifier, time);
        // 获取指令
        return new OrderCmd(ConvertUtil.crcEncrypt(content, header));
    }

    /**
     * 获取gps指令
     * 
     * @return
     */
    public OrderCmd getGPSDataCmd()
    {
        return new OrderCmd(getSimpleCmd(new byte[] { 0x02, 0x43 }));
    }

    /**
     * 获取唤醒指令
     * 
     * @return
     */
    public byte[] getWakeUpCmd()
    {
        return getSimpleCmd(new byte[] { 0x55, 0x55 });
    }

    /**
     * 获取通用应答指令
     * 
     * @return
     */
    public OrderCmd getNormalCmd(int obdSerialNum)
    {
        // 报文序列号,占用2字节
        byte[] serialNum = getSerialNum();
        // 命令标识,占用2个字节
        byte[] cmdIdentifier = new byte[] { 0x60, 0x01 };
        // 接收的报文流水号
        byte[] obdSerialByte = ConvertUtil.shortToBytes((short) obdSerialNum, true);
        // 结果
        byte[] result = new byte[] { 0x00 };
        // 内容
        byte[] content = ConvertUtil.byteMerger(serialNum, cmdIdentifier, obdSerialByte, result);
        // 获取指令
        return new OrderCmd(ConvertUtil.crcEncrypt(content, header));
    }

    /**
     * 获取仅和指令相关的命令内容
     * 
     * @param cmd
     * @return
     */
    private byte[] getSimpleCmd(byte[] cmd)
    {
        // 报文序列号,占用2字节
        byte[] serialNum = getSerialNum();
        // 命令标识,占用2个字节
        byte[] cmdIdentifier = cmd;
        // 内容
        byte[] content = ConvertUtil.byteMerger(serialNum, cmdIdentifier);
        // 获取指令
        return ConvertUtil.crcEncrypt(content, header);
    }

    /**
     * 获取流水号（序列号）
     * 
     * @return
     */
    private byte[] getSerialNum()
    {
        return AtomicIntegerUtil.getIncrementBytesID();
    }

}
